package ch.msoftch.gui.utils;

import static org.eclipse.jdt.core.dom.Modifier.ModifierKeyword.*;
import java.io.*;
import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;

/**
 * Class building a property key class.
 * 
 * @author hautle
 */
public class PropertyKeyClassBuilder extends ClassBuilder {
    /** The properties file. */
    private final IFile properties;

    /** The name of the properties file (without suffix). */
    private final String propName;

    /**
     * Default constructor.
     * 
     * @param properties The input file
     * @throws CoreException
     */
    private PropertyKeyClassBuilder(IFile properties) throws CoreException {
        this.properties = properties;
        final int len = properties.getFileExtension().length();
        final String name = properties.getName();
        propName = name.substring(0, name.length() - len - 1);
    }

    /**
     * Returns the package which contains the properties file
     * 
     * @return The package
     * @throws CoreException
     */
    private IPackageFragment getPackage() throws CoreException {
        final IJavaProject jp = (IJavaProject) properties.getProject().getNature(JavaCore.NATURE_ID);
        return jp.findPackageFragment(properties.getParent().getFullPath());
    }

    /**
     * Returns the class name for the class to create.
     * 
     * @return The class name
     */
    private String getClassName() {
        final StringBuilder str = new StringBuilder();
        str.append(propName);
        str.append("Keys");
        str.setCharAt(0, Character.toUpperCase(propName.charAt(0)));
        return str.toString();
    }

    /**
     * Initializes the class.
     * 
     * @throws CoreException
     */
    private void init() throws CoreException {
        final String name = getClassName();
        final IPackageFragment pkg = getPackage();
        final ICompilationUnit unit = pkg.createCompilationUnit(name + ".java", "", true, null);
        setUp(unit);
        createMainType(PUBLIC_KEYWORD, pkg.getElementName(), getClassName());
    }

    /**
     * Parses the properties file and creates the corresponding constant entries.
     * 
     * @throws IOException
     * @throws CoreException
     */
    private void parse() throws IOException, CoreException {
        BufferedReader in = null;
        try {
            in = new BufferedReader(new InputStreamReader(properties.getContents()));
            for (String s = in.readLine(); s != null; s = in.readLine()) {
                if (s.charAt(0) == '#' || s.length() == 0)
                    continue;
                final int delim = s.indexOf('=');
                createEntry(s.substring(0, delim).trim());
            }
        } finally {
            if (in != null)
                in.close();
        }
    }

    /**
     * Creates a constant for the given property.
     * 
     * @param property The property name
     */
    private void createEntry(String property) {
        addField(createField("String", getConstantName(property), createString(property), PUBLIC_KEYWORD, STATIC_KEYWORD, FINAL_KEYWORD));
    }

    /**
     * Retruns the name for a constant for the given property.
     * 
     * @param property The property name
     * @return The corresponding constant name
     */
    private String getConstantName(String property) {
        final StringBuilder str = new StringBuilder(property.length() + 10);
        for (int i = 0, len = property.length(); i < len; i++) {
            final char c = property.charAt(i);
            switch (c) {
                case '-':
                case '.':
                    str.append('_');
                    break;
                default:
                    if (!Character.isJavaIdentifierPart(c))
                        continue;
                    if (Character.isUpperCase(c))
                        str.append('_').append(c);
                    else
                        str.append(Character.toUpperCase(c));
            }
        }
        return str.toString();
    }

    /**
     * Creates a properties class for the given properties file.
     * 
     * @param properties The properties file
     * @throws IOException
     * @throws CoreException
     */
    public static void create(IFile properties) throws IOException, CoreException {
        final PropertyKeyClassBuilder p = new PropertyKeyClassBuilder(properties);
        p.init();
        p.parse();
        p.write();
    }
}
